import cryptoFramework from '@ohos.security.cryptoFramework'
import { ByteUtils } from './ByteUtils'

const defaultAlgName = "3DES192"
const defaultTransformation = "3DES192|CBC|PKCS5"
const defaultIv = "66666666"

export class TripleDESUtils {
  /**
   * 生成3DES密钥
   */
  static gen3DesKey(algName: string = defaultAlgName): Promise<cryptoFramework.SymKey> {
    return cryptoFramework.createSymKeyGenerator(algName).generateSymKey()
  }

  /**
   * 转换3DES密钥
   * @param key 密钥
   */
  static convertKeySync(key: Uint8Array, algName: string = defaultAlgName): cryptoFramework.SymKey {
    if (key.length < 24) {
      throw "The key length cannot be less than 24"
    }
    let nKey = key.subarray(0, 24)
    return cryptoFramework.createSymKeyGenerator(algName).convertKeySync({
      data: nKey
    })
  }

  /**
   * 转换3DES密钥
   * @param key 密钥
   */
  static convertKey(key: Uint8Array, algName: string = defaultAlgName): Promise<cryptoFramework.SymKey> {
    return new Promise(function (resolve, reject) {
      if (key.length < 24) {
        reject("The key length cannot be less than 24")
        return
      }
      let nKey = key.subarray(0, 24)
      cryptoFramework.createSymKeyGenerator(algName).convertKey({
        data: nKey
      }).then(res => {
        resolve(res)
      }).catch(err => {
        reject(err)
      })
    })
  }

  /**
   * 转换3DES密钥
   * @param key 密钥
   */
  static encryptSync(key: cryptoFramework.SymKey, data: Uint8Array,
    transformation: string = defaultTransformation, iv: string = defaultIv): Uint8Array {
    let cipher = cryptoFramework.createCipher(transformation)
    let ivDataBlob: cryptoFramework.DataBlob = {
      data: ByteUtils.stringToUtf8Bytes(iv)
    }
    let ivParams: cryptoFramework.IvParamsSpec = {
      algName: "IvParamsSpec",
      iv: ivDataBlob
    }
    cipher.initSync(cryptoFramework.CryptoMode.ENCRYPT_MODE, key, ivParams)
    return cipher.doFinalSync({
      data: data
    }).data
  }

  /**
   * 加密
   * @param key 秘钥
   * @param data 待加密数据
   * @returns 密文
   */
  static encrypt(key: cryptoFramework.SymKey, data: Uint8Array,
    transformation: string = defaultTransformation, iv: string = defaultIv): Promise<Uint8Array> {
    return new Promise(function (resolve, reject) {
      let cipher = cryptoFramework.createCipher(transformation)
      let ivDataBlob: cryptoFramework.DataBlob = {
        data: ByteUtils.stringToUtf8Bytes(iv)
      }
      let ivParams: cryptoFramework.IvParamsSpec = {
        algName: "IvParamsSpec",
        iv: ivDataBlob
      }
      cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, key, ivParams).then(() => {
        return cipher.doFinal({
          data: data
        })
      }).then((value) => {
        resolve(value.data)
      }).catch(err => {
        reject(err)
      })
    })
  }

  /**
   * 解密
   * @param key 密钥
   * @param data 密文
   * @returns 明文
   */
  static decrypt(key: cryptoFramework.SymKey, data: Uint8Array,
    transformation: string = defaultTransformation, iv: string = defaultIv): Promise<Uint8Array> {
    return new Promise(function (resolve, reject) {
      let cipher = cryptoFramework.createCipher(transformation)
      let ivDataBlob = {
        data: ByteUtils.stringToUtf8Bytes(iv)
      }
      let ivParams = {
        algName: "IvParamsSpec",
        iv: ivDataBlob
      }
      cipher.init(cryptoFramework.CryptoMode.DECRYPT_MODE, key, ivParams).then(() => {
        return cipher.doFinal({
          data: data
        })
      }).then((value) => {
        resolve(value.data)
      }).catch(err => {
        reject(err)
      })
    })
  }
}